package com.hardson.toolkit.util;

import org.apache.commons.lang3.RandomUtils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

public class IDUtils {
    private static final IDWorker worker = IDWorker.create();

    /**
     * 获得一个去掉了连字符“-”的UUID
     *
     * @return String UUID
     */
    public static String getUUID() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 通过UUID的散列码构建全局唯一数字ID
     * 目前观察到的UUID的散列码值的长度为7~10位，含7位和10位。
     * 注意：此方法只能确保重复的概率极小，而不能保证绝对唯一。有网友测试，用此方法并发生成100万个ID，没有出现重复。
     *
     * @return 全局唯一数字ID
     */
    public static int getUUIDOfHashCode() {
        int uuidHash = getUUID().hashCode();
        return Math.abs(uuidHash);// 可能是负数，所以取绝对值
    }

    public static String getUUIDHashCodeStr() {
        return String.valueOf(getUUIDOfHashCode());
    }

    /**
     * 通过UUID的散列码构建定长为10位的全局唯一字符串数字ID
     * 构成规则：不足10位的在前端以随机数补足
     *
     * @return String
     * @author hardson
     * @date 2023/9/20 下午4:09
     */
    public static String getID10ByUUIDStr() {
        int hashCode = getUUIDOfHashCode();
        String str = String.valueOf(hashCode);
        int len = str.length();
        switch (len) {
            case 10:
                return str;
            case 9:
                return RandomUtils.nextInt(1, 10) + str;
            case 8:
                return RandomUtils.nextInt(10, 100) + str;
            case 7:
                return RandomUtils.nextInt(100, 1000) + str;
        }

        // %010d:   0 代表前面补充0，10 代表长度为10，d 代表参数为正数型
        return String.format("%010d", hashCode);
    }

    /**
     * 通过UUID的散列码构建定长为10位的全局唯一数字ID
     * 不足10位的在前端以随机数补足
     *
     * @return long
     * @author hardson
     * @date 2023/9/20 下午4:13
     */
    public static long getID10ByUUID() {
        return Long.parseLong(getID10ByUUIDStr());
    }

    /**
     * 通过UUID的hashCode构建16位ID
     * 构成规则：两位机器ID+月日+10位ID
     *
     * @param machineId 两位数的机器ID
     * @return String
     */
    public static String getID16ByUUID(final String machineId) {
        String machineId_ = StrUtil.trimEmpty(machineId);
        if (machineId.length() != 2) {
            throw new IllegalArgumentException("机器ID必须为两位字符串，错误参数为：" + machineId);
        }
        // 中间四位整数，标识日期（月日）
        SimpleDateFormat sdf = new SimpleDateFormat("MMdd");
        String dayTime = sdf.format(new Date());
        return machineId_ + dayTime + getID10ByUUIDStr();
    }

    /**
     * 通过UUID的hashCode构建以年月日开头的16位ID
     *
     * @return String
     */
    public static String getID16ByUUIDStr() {

        // 中间四位整数，标识日期（月日）
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
        String dayTime = sdf.format(new Date());
        return dayTime + getID10ByUUIDStr();
    }

    /**
     * 通过UUID的hashCode构建以年月日开头的16位长整数ID
     *
     * @return 以年月日开头的16位长整数ID
     */
    public static long getID16ByUUID() {
        String orderId = getID16ByUUIDStr();
        return Long.parseLong(orderId);
    }

    /**
     * 通过UUID的hashCode构建以年月开头的14位ID
     *
     * @return String
     */
    public static String getID14ByUUIDStr() {

        // 中间四位整数，标识日期（月日）
        SimpleDateFormat sdf = new SimpleDateFormat("yyMM");
        String dayTime = sdf.format(new Date());
        return dayTime + getID10ByUUIDStr();
    }

    /**
     * 通过UUID的hashCode构建以年月开头的14位长整数ID
     *
     * @return 以年月日开头的14位长整数ID
     */
    public static long getID14ByUUID() {
        String orderId = getID14ByUUIDStr();
        return Long.parseLong(orderId);
    }

    public static long getSnowflakeId() {
        return worker.nextId();
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100000; i++) {
            System.out.println(worker.nextId());
        }
    }
}
